#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Nov  4 22:09:24 2021

@author: xiechongwu
"""
import board
import digitalio
import adafruit_max31865
import RPi.GPIO as GPIO
import time

spi = board.SPI()
cs = digitalio.DigitalInOut(board.D5)
sensor = adafruit_max31865.MAX31865(spi, cs, wires=3)
# aim temperature
tem = 25
# initial the channels
channel_1 = 20
channel_2 = 21
outputlist = [channel_1, channel_2]
GPIO.setup(outputlist, GPIO.OUT, initial=GPIO.LOW)
GPIO.output(channel_2, GPIO.HIGH)

class pid:
    """the pid control function.
    """
    def __init__(self, kp=0.6, ki=0, kd=0, ku=100):
        """
        Initialize the pid
        
        Paramters
        ---------
        kp: float, optional
            coefficients for the proportional term.
        ki: float, optional
            coefficients for the integral term.
        kd: float, optional
            coefficients for the derivative term.
        ku: float, optional
            ultimate gain.
        """
        
        self.ki = ki
        self.kp = kp
        self.kd = kd
        self.ku = ku
        self.ui = 0
        self.up = 0
        self.ud = 0
        self.u = 0
        self.error = 0
    def update(self, error, dt):
        """
        Update the control function and output it
        
        Paramters
        ---------
        error: float
            error signal.
        dt: float
            time period.
        """        
        ku = self.ku
        if self.error == 0 :
            self.error = error
        derror = error - self.error
        self.ui += self.ki * ku * error * dt
        self.up = self.kp * ku * error
        self.ud = self.kd * ku * derror/dt
        self.u = self.ui + self.up + self.ud
        self.error = error
        
try:
    dt = 0.05
    N = 0
    pid_u = pid()
    while(1):
        p_tem = sensor.temperature
        error = p_tem - tem
        pid_u.update(error, dt)
        u = pid_u.u
        if u < 0:
            GPIO.output(channel_2, GPIO.LOW)
            if u <= -80:
                GPIO.output(channel_1, GPIO.HIGH)
            else:
                freq = 1000
                pwm = GPIO.PWM(channel_2, freq)
                dc = -u + 20
                pwm.start(dc)
        else:
            GPIO.output(channel_1, GPIO.LOW)
            if u >= 80:
                GPIO.output(channel_2, GPIO.HIGH)
            else:
                freq = 1000
                pwm = GPIO.PWM(channel_1, freq)
                dc = u + 20
                pwm.start(dc)
        time.sleep(dt)
        pwm.stop()
        N += 1
    	# 每隔1s打印一次输出
        if N%20 == 0:
            print("Temperature: {0:0.3f}".format(p_tem))
            print("error: {0:0.3f}".format(error))
            print("dc: {0:0.3f}".format(u))
            print("*========================*")
finally:
    pwm.stop()
    GPIO.cleanup()

